load("//bazel:ray.bzl", "define_java_module")
load("//bazel:ray.bzl", "native_java_binary")
load("//bazel:ray.bzl", "native_java_library")
load("@rules_proto_grpc//java:defs.bzl", "java_proto_compile")
load(
    "@com_github_johnynek_bazel_jar_jar//:jar_jar.bzl",
    "jar_jar",
)

exports_files([
    "testng.xml",
    "checkstyle.xml",
    "checkstyle-suppressions.xml",
])

all_modules = [
    "api",
    "runtime",
    "serve",
    "test",
    "performance_test",
]

java_import(
    name = "all_modules",
    jars = [
        "libio_ray_ray_" + module + ".jar"
        for module in all_modules
    ] + [
        "libio_ray_ray_" + module + "-src.jar"
        for module in all_modules
    ] + [
        "all_tests_deploy.jar",
        "all_tests_deploy-src.jar",
    ],
    deps = [
        ":io_ray_ray_" + module
        for module in all_modules
    ] + [
        ":all_tests",
    ],
)

define_java_module(
    name = "api",
    visibility = ["//visibility:public"],
    deps = [
        "@maven//:com_lmax_disruptor",
        "@maven//:com_sun_xml_bind_jaxb_core",
        "@maven//:com_sun_xml_bind_jaxb_impl",
        "@maven//:javax_activation_activation",
        "@maven//:javax_xml_bind_jaxb_api",
        "@maven//:org_apache_logging_log4j_log4j_api",
        "@maven//:org_apache_logging_log4j_log4j_core",
        "@maven//:org_apache_logging_log4j_log4j_slf4j_impl",
        "@maven//:org_slf4j_slf4j_api",
    ],
)

define_java_module(
    name = "runtime",
    additional_resources = [
        ":java_native_deps",
    ],
    additional_srcs = [
        ":all_java_proto",
    ],
    define_test_lib = True,
    exclude_srcs = [
        "runtime/src/main/java/io/ray/runtime/generated/*.java",
    ],
    test_deps = [
        ":io_ray_ray_api",
        ":io_ray_ray_runtime",
        "@maven//:commons_io_commons_io",
        "@maven//:javax_xml_bind_jaxb_api",
        "@maven//:org_apache_commons_commons_lang3",
        "@maven//:org_testng_testng",
    ],
    visibility = ["//visibility:public"],
    deps = [
        ":io_ray_ray_api",
        "@maven//:com_fasterxml_jackson_core_jackson_databind",
        "@maven//:com_github_java_json_tools_json_schema_validator",
        "@maven//:com_google_code_gson_gson",
        "@maven//:com_google_guava_guava",
        "@maven//:com_google_protobuf_protobuf_java",
        "@maven//:com_google_protobuf_protobuf_java_util",
        "@maven//:com_lmax_disruptor",
        "@maven//:com_typesafe_config",
        "@maven//:commons_io_commons_io",
        "@maven//:de_ruedigermoeller_fst",
        "@maven//:net_java_dev_jna_jna",
        "@maven//:org_apache_commons_commons_lang3",
        "@maven//:org_apache_logging_log4j_log4j_api",
        "@maven//:org_apache_logging_log4j_log4j_core",
        "@maven//:org_apache_logging_log4j_log4j_slf4j_impl",
        "@maven//:org_msgpack_msgpack_core",
        "@maven//:org_ow2_asm_asm",
        "@maven//:org_slf4j_slf4j_api",
        "@maven//:org_testng_testng",
    ],
)

define_java_module(
    name = "test",
    # (WangTaoTheTonic)For cpp x-lang tests. See //cpp:cluster_mode_xlang_test.
    visibility = ["//cpp:__subpackages__"],
    deps = [
        ":io_ray_ray_api",
        ":io_ray_ray_runtime",
        "@maven//:com_google_code_gson_gson",
        "@maven//:com_google_guava_guava",
        "@maven//:com_google_protobuf_protobuf_java",
        "@maven//:com_lmax_disruptor",
        "@maven//:com_sun_xml_bind_jaxb_core",
        "@maven//:com_sun_xml_bind_jaxb_impl",
        "@maven//:commons_io_commons_io",
        "@maven//:javax_xml_bind_jaxb_api",
        "@maven//:org_apache_commons_commons_lang3",
        "@maven//:org_apache_logging_log4j_log4j_api",
        "@maven//:org_apache_logging_log4j_log4j_core",
        "@maven//:org_apache_logging_log4j_log4j_slf4j_impl",
        "@maven//:org_slf4j_slf4j_api",
        "@maven//:org_testng_testng",
    ],
)

define_java_module(
    name = "performance_test",
    deps = [
        ":io_ray_ray_api",
        ":io_ray_ray_runtime",
        "@maven//:com_google_code_gson_gson",
        "@maven//:com_google_guava_guava",
        "@maven//:com_lmax_disruptor",
        "@maven//:commons_io_commons_io",
        "@maven//:org_apache_commons_commons_lang3",
        "@maven//:org_apache_logging_log4j_log4j_api",
        "@maven//:org_apache_logging_log4j_log4j_core",
        "@maven//:org_apache_logging_log4j_log4j_slf4j_impl",
        "@maven//:org_slf4j_slf4j_api",
    ],
)

define_java_module(
    name = "serve",
    additional_srcs = [
        ":serve_java_proto",
    ],
    define_test_lib = True,
    exclude_srcs = [
        "serve/src/main/java/io/ray/serve/generated/*.java",
    ],
    test_deps = [
        ":io_ray_ray_api",
        ":io_ray_ray_runtime",
        ":io_ray_ray_serve",
        "@maven//:com_google_code_gson_gson",
        "@maven//:com_google_guava_guava",
        "@maven//:com_google_protobuf_protobuf_java",
        "@maven//:commons_io_commons_io",
        "@maven//:org_apache_commons_commons_lang3",
        "@maven//:org_apache_httpcomponents_client5_httpclient5",
        "@maven//:org_apache_httpcomponents_client5_httpclient5_fluent",
        "@maven//:org_apache_httpcomponents_core5_httpcore5",
        "@maven//:org_slf4j_slf4j_api",
        "@maven//:org_testng_testng",
    ],
    visibility = ["//visibility:public"],
    deps = [
        ":io_ray_ray_api",
        ":io_ray_ray_runtime",
        "@maven//:com_google_code_gson_gson",
        "@maven//:com_google_guava_guava",
        "@maven//:com_google_protobuf_protobuf_java",
        "@maven//:org_apache_commons_commons_lang3",
        "@maven//:org_apache_httpcomponents_core5_httpcore5",
        "@maven//:org_slf4j_slf4j_api",
    ],
)

java_library(
    name = "all_tests_lib",
    runtime_deps = [
        ":io_ray_ray_performance_test",
        ":io_ray_ray_runtime_test",
        ":io_ray_ray_serve_test",
        ":io_ray_ray_test",
    ],
)

java_test(
    name = "all_tests",
    testonly = True,
    args = ["java/testng.xml"],
    data = [
        "testng.xml",
        ":ray_java_pkg",
        "//:ray_pkg",
    ],
    main_class = "org.testng.TestNG",
    resources = [
        "//cpp:counter.so",
        "//cpp:plus.so",
    ],
    tags = ["local"],
    runtime_deps = [
        ":all_tests_lib",
    ],
)

# 0. `cp testng_custom_template.xml testng_custom.xml`
# 1. Specify test class/method in `testng_custom.xml`
# 2. `bazel test //java:custom_test --test_output=streamed`
java_test(
    name = "custom_test",
    args = ["java/testng_custom.xml"],
    data = [
        "testng_custom.xml",
        ":ray_java_pkg",
        "//:ray_pkg",
    ],
    main_class = "org.testng.TestNG",
    tags = ["local"],
    runtime_deps = [
        ":all_tests_lib",
    ],
)

# We'd better make resource files can be accessed from 3rd party library.
# More detail please see https://github.com/ray-project/ray/pull/21641.
java_proto_compile(
    name = "common_java_proto",
    deps = ["@com_github_ray_project_ray//src/ray/protobuf:common_proto"],
)

java_proto_compile(
    name = "runtime_env_common_java_proto",
    deps = ["@com_github_ray_project_ray//src/ray/protobuf:runtime_env_common_proto"],
)

java_proto_compile(
    name = "gcs_java_proto",
    deps = ["@com_github_ray_project_ray//src/ray/protobuf:gcs_proto"],
)

java_proto_compile(
    name = "serve_java_proto",
    deps = ["@com_github_ray_project_ray//src/ray/protobuf:serve_proto"],
)

filegroup(
    name = "all_java_proto",
    srcs = [
        ":common_java_proto",
        ":gcs_java_proto",
        ":runtime_env_common_java_proto",
    ],
)

native_java_library("runtime", "core_worker_library_java", "//src/ray/core_worker/lib/java:libcore_worker_library_java.so")

filegroup(
    name = "java_native_deps",
    srcs = [
        ":core_worker_library_java",
    ],
)

# Generates the dependencies needed by maven.
genrule(
    name = "cp_java_generated",
    srcs = [
        ":all_java_proto",
        ":copy_pom_file",
        ":serve_java_proto",
    ],
    outs = ["cp_java_generated.out"],
    cmd = """
        WORK_DIR="$$(pwd)"
        # Copy protobuf-generated files.
        rm -rf "$$WORK_DIR/java/runtime/src/main/java/io/ray/runtime/generated"
        echo "# cp_java_generated" > $@
        for f in $(locations //java:all_java_proto); do
            unzip "$$f" -x META-INF/MANIFEST.MF -d "$$WORK_DIR/java/runtime/src/main/java"
            if [[ "$$OSTYPE" =~ ^darwin ]]; then shasum "$$f" >> $@ ; else sha1sum "$$f" >> $@ ; fi
        done
        rm -rf "$$WORK_DIR/java/serve/src/main/java/io/ray/serve/generated"
        for f in $(locations //java:serve_java_proto); do
            unzip "$$f" -x META-INF/MANIFEST.MF -d "$$WORK_DIR/java/serve/src/main/java"
            if [[ "$$OSTYPE" =~ ^darwin ]]; then shasum "$$f" >> $@ ; else sha1sum "$$f" >> $@ ; fi
        done
    """,
    local = 1,
    tags = ["no-cache"],
)

# Generates the dependencies needed by maven.
genrule(
    name = "gen_maven_deps",
    srcs = [
        ":cp_java_generated",
        ":java_native_deps",
    ],
    outs = ["gen_maven_deps.out"],
    cmd = """
        WORK_DIR="$${PWD}"
        # Copy native dependencies.
        OS_NAME=""
        case "$${OSTYPE}" in
          linux*) OS_NAME="linux";;
          darwin*) OS_NAME="darwin";;
          *) echo "$${OSTYPE} is not supported currently"; exit 1;;
        esac
        NATIVE_DEPS_DIR="$$WORK_DIR/java/runtime/native_dependencies/native/$$OS_NAME"
        rm -rf "$$NATIVE_DEPS_DIR"
        mkdir -p "$$NATIVE_DEPS_DIR"
        echo "# gen_maven_deps" > $@
        for f in $(locations //java:java_native_deps); do
            chmod +w "$$f"
            cp "$$f" "$$NATIVE_DEPS_DIR"
            if [[ "$$OSTYPE" =~ ^darwin ]]; then shasum "$$f" >> $@ ; else sha1sum "$$f" >> $@ ; fi
        done
    """,
    local = 1,
    tags = ["no-cache"],
)

genrule(
    name = "copy_pom_file",
    srcs = [
        "//java:io_ray_ray_" + module + "_pom"
        for module in all_modules
    ],
    outs = ["copy_pom_file.out"],
    cmd = """
        WORK_DIR="$$(pwd)"
        cp -f $(location //java:io_ray_ray_api_pom) "$$WORK_DIR/java/api/pom.xml"
        cp -f $(location //java:io_ray_ray_runtime_pom) "$$WORK_DIR/java/runtime/pom.xml"
        cp -f $(location //java:io_ray_ray_test_pom) "$$WORK_DIR/java/test/pom.xml"
        cp -f $(location //java:io_ray_ray_performance_test_pom) "$$WORK_DIR/java/performance_test/pom.xml"
        cp -f $(location //java:io_ray_ray_serve_pom) "$$WORK_DIR/java/serve/pom.xml"

        FILES=(
            $(location //java:io_ray_ray_api_pom)
            $(location //java:io_ray_ray_runtime_pom)
            $(location //java:io_ray_ray_test_pom)
            $(location //java:io_ray_ray_performance_test_pom)
            $(location //java:io_ray_ray_serve_pom)
        )
        echo "# copy_pom_file" > $@
        if [[ "$$OSTYPE" =~ ^darwin ]]; then shasum "$${FILES[@]}" > $@ ; else sha1sum "$${FILES[@]}" >> $@ ; fi
    """,
    local = 1,
    tags = ["no-cache"],
)

java_binary(
    name = "ray_dist",
    # This rule is used to package all Ray Java code and the third-party dependencies into a
    # fat jar file. It's not really an executable jar. So we set its `main_class` to empty.
    main_class = "",
    runtime_deps = [
        "//java:io_ray_ray_api",
        "//java:io_ray_ray_runtime",
        "//java:io_ray_ray_serve",
    ],
)

jar_jar(
    name = "ray_dist_shaded",
    input_jar = "//java:ray_dist_deploy.jar",
    rules = "//java:shade_rule",
)

# Shade dependencies in tests fat jar.
jar_jar(
    name = "all_tests_shaded",
    input_jar = "//java:all_tests_deploy.jar",
    rules = "//java:shade_rule",
)

genrule(
    name = "ray_java_pkg",
    srcs = [
        "//java:ray_dist_shaded.jar",
        "//java:gen_maven_deps",
    ],
    outs = ["ray_java_pkg.out"],
    cmd = """
        WORK_DIR="$$(pwd)"
        rm -rf "$$WORK_DIR/python/ray/jars" && mkdir -p "$$WORK_DIR/python/ray/jars"
        cp -f $(location //java:ray_dist_shaded.jar) "$$WORK_DIR/python/ray/jars/ray_dist.jar"
        echo "# ray_java_pkg" > $@
        OUTPUT_JAR="$(location //java:ray_dist_shaded.jar)"
        if [[ "$$OSTYPE" =~ ^darwin ]]; then shasum "$$OUTPUT_JAR" >> $@ ; else sha1sum "$$OUTPUT_JAR" >> $@ ; fi
    """,
    local = 1,
    tags = ["no-cache"],
)
